home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 6 / The Arsenal Files 6 (Arsenal Computer).ISO / prg_basi / n_b-v200.zip / NBT2 / DMO / TINPUT.TXT < prev    next >
Text File  |  1996-03-11  |  26KB  |  507 lines

  1. $if 0
  2.     ┌──────────────────────────╖                        PowerBASIC v3.20
  3.  ┌──┤          DASoft          ╟──────────────────────┬──────────────────╖
  4.  │  ├──────────────────────────╢    Copyright 1995    │ DATE: 1995-10-01 ╟─╖
  5.  │  │ FILE NAME   TINPUT  .TXT ║          by          ╘════════════════─ ║ ║
  6.  │  │                          ║  Don Schullian, Jr.                     ║ ║
  7.  │  ╘══════════════════════════╝                                         ║ ║
  8.  │ A license is hereby granted to the holder to use this source code in  ║ ║
  9.  │ any program, commercial or otherwise,  without receiving the express  ║ ║
  10.  │ permission of the copyright holder and without paying any royalties,  ║ ║
  11.  │ as long as this code is not distributed in any compilable format.     ║ ║
  12.  │  IE: source code files, PowerBASIC Unit files, and printed listings   ║ ║
  13.  ╘═╤═════════════════════════════════════════════════════════════════════╝ ║
  14.    │                ....................................                   ║
  15.    ╘═══════════════════════════════════════════════════════════════════════╝
  16. $endif
  17.  
  18.  ┌──────────────────────────────────────────────────────────────────┐
  19.  │   fTinput$ and fTinputM$ both use the same TINPUT_?.INC files.   │
  20.  └──────────────────────────────────────────────────────────────────┘
  21.  
  22.  Before you get into all of this: The info in this file is vital but,
  23.  despite the length of the file it is  NOT difficult to understand if
  24.  you don't try to make it into something more than it is. The concept
  25.  was taught to me by my guru in about 30 seconds on the margin of the
  26.  daily news paper! So, if I can grasp it that fast, nuff said! d;D
  27.  
  28.  A program is not worth much if it cannot input data and instructions
  29.  from the user; how this information  and data is input is one of the
  30.  most important features of any program.  It should be as easy and as
  31.  fool-proof as possible. Your job, as programmer, is to make all this
  32.  happen.
  33.  
  34.  As there are several different types of data one all-purpose routine
  35.  just doesn't make the cut!  On the other hand, to attempt to have an
  36.  individual routine for each style is just too much to handle. I have
  37.  come up with a happy medium:  a suite of routines that allows you to
  38.  call a single function from within your program. It calls a specific
  39.  handler for the data style required.  Sorta' like one stop shopping!
  40.  
  41.  There are 9 field styles. Eight of them provide specific support and
  42.  the ninth is a general,  all-purpose field  that catches  everything
  43.  else.  The fields are controlled by a string of data  that you send.
  44.  The string is loaded into a TYPE by the function before it is passed
  45.  to the specific handler.
  46.  
  47.  As you can see the first  8 bytes of the control string fit into the
  48.  TYPE  but from position nine and on  you can also send more data for
  49.  some of the styles that require it  or can use it.  This area of the
  50.  string is known an the MASK.  Also, not all the members of the  TYPE
  51.  are used by all the styles and  .Misc is a kind of catch-all member.
  52.  Despite their comings and goings,  the members hold their purpose in
  53.  life throughout.  Below is a generalized description for each member
  54.  then a style by style discussion.
  55.  
  56.  ┌──────────────────────────────────────────────────────────────────┐
  57.  │ One important thing to remember is that fTinput assumes that the │
  58.  │ incoming data is IN THE CORRECT FORMAT for the designated Style. │
  59.  └──────────────────────────────────────────────────────────────────┘
  60.  
  61.  TYPE TinputTYPE             '┌───────────────────────────────────
  62.    Style  AS STRING * 1      '│ field type ie: A,B,D,H,M,N,P,Q,T
  63.    Row    AS BYTE            '│ screen row
  64.    Col    AS BYTE            '│ left most screen column
  65.    Cols   AS BYTE            '│ N° of visible columns
  66.    MustBe AS BYTE            '│ > 0 if field is mandatory
  67.    Cased  AS BYTE            '│ 0 = none 1 = UCASEed 2 = LCASEed
  68.    Misc   AS BYTE            '│ max length of string => Cols
  69.    Just   AS BYTE            '│ N° of routine to call fJUSTIFY$ with
  70.  END TYPE                    '└────────────────────────┤ 9 bytes ├───
  71.  
  72.  .Style   always indicates which field driver to use
  73.  .Row     always the starting screen row for the field
  74.  .Col     always the left-most column(s) for the field
  75.  .Cols    always the maximum visible columns of the field
  76.           in most cases this is also the maximum length of the field
  77.  .MustBe  if > 0 then the field is mandatory
  78.           this field is used differently by each style
  79.  .Cased   if 0 then no casing is done to the input
  80.           if 1 then all input is UCASEd using UCASEstr
  81.           if 2 then all input is LCASEd using LCASEstr
  82.  .Misc    used differently by each style
  83.  .Just    an extra byte for your use as it is NOT used by fTinput$
  84.  
  85.  ──────────────────────────────────────────────────────────────────────────
  86.  ANYTHING GOES
  87.  ──────────────────────────────────────────────────────────────────────────
  88.   Style  = "A"         Anything goes
  89.   Row    = 1 -> x      screen row
  90.   Col    = 1 -> x      left most screen column
  91.   Cols   = 1 -> x      N° of visible columns
  92.   MustBe = 0 or x      > 0 if field is mandatory
  93.   Cased  = 0, 1 or 2   0 = NOCASING 1 = UCASEed 2 = LCASEed
  94.   Misc   = x           maximum field length if => Cols
  95.   Just   = x           NOT USED
  96.   Mask$  =             if NULL any characters accepted
  97.                        ELSE only chars in Mask$ eg: " 0123456789-"
  98.  
  99.   DATA IN : any string value from NULL to .Misc in length
  100.   DATA OUT: a string of up to .Col or .Misc length
  101.  
  102.   As you can see this field can and will scroll through a long string of
  103.   data. By using Mask$ you can restrict the keyboard input to only a few
  104.   keys. ie: "0123456789-() " works well for phone numbers
  105.  
  106.   Another property of Alpha is that it will automatically issue a CHR$(13)
  107.   if .Cols = 1 and an acceptable key is input. This allows you to use ALPHA
  108.   for yes/no answers and the like, but QUERY does a better job of it.
  109.  
  110.  ──────────────────────────────────────────────────────────────────────────
  111.  BLOCK O' TEXT
  112.  ──────────────────────────────────────────────────────────────────────────
  113.   Style  = "B"         Block of text
  114.   Row    = 1 -> x      top most screen row
  115.   Col    = 1 -> x      left most screen column
  116.   Cols   = 1 -> x      N° of columns
  117.   MustBe = NOT USED    0 is assumed
  118.   Cased  = NOT USED    0 is assumed
  119.   Misc   = x           maximum number of rows of .Cols chars
  120.   Just   = NOT USED
  121.   Mask$  = NOT USED
  122.  
  123.   DATA IN : any string of text
  124.   DATA OUT: a string of text
  125.  
  126.   A simple word-wrap is employed SEE: fWrapPosF%
  127.   <UP> and <DOWN> keys are used and <ENTER> acts as <DOWN>
  128.   fTinput$ can return <UP> and <DOWN> as defaults from this function
  129.  
  130.  ──────────────────────────────────────────────────────────────────────────
  131.  DATES
  132.  ──────────────────────────────────────────────────────────────────────────
  133.   Style  = "D"         Dates
  134.   Row    = 1 -> x      screen row
  135.   Col    = 1 -> x      left most screen column
  136.   Cols   = 8 or 10     8 is default ( + LEN(day$) )
  137.   MustBe = 0 or x      > 0 if field is mandatory
  138.   Cased  = NOT USED
  139.   Misc   = NOT USED
  140.   Just   = NOT USED
  141.   Mask$  = "Sun |Mon |Tue |Wed |Thr |Fri |Sat "
  142.                        NOTE: if Mask$ is used
  143.                              * all day names need be the same length
  144.                              * .Cols must include this length
  145.                              * D$ is _NOT_ effected
  146.                              The data field looks like "Mon 01-01-1995"
  147.                              and the user only inputs the date not the
  148.                              day.
  149.  DATA IN : an 8 or 10 character date string in SetDateFormat style
  150.  DATA OUT: same as data in
  151.  
  152.  If .MustBe > 0 and incoming D$ is NULL then the system's date is used
  153.  ELSE
  154.  Before the field exits the date entered must be a correct and legal date
  155.  or a NULL field will exit with a value of SPACE$(.Cols) and display.
  156.  
  157.  The grey       "*" resets the date to the current date
  158.                 "-" -  1 day  (yesterday)  ' these keys come in handy, along
  159.           <CTRL>"-" - 28 days ( 4 weeks)   ' with the day of the week for
  160.           <ALT> "-" -364 days (52 weeks)   ' businesses that need to set-up
  161.                 "+" +  1 day  (yesterday)  ' appointments, meetings, etc.
  162.           <CTRL>"+" + 28 days ( 4 weeks)   '
  163.           <ALT> "+" +364 days (52 weeks)   '
  164.  ───────────────────────────────────────────────────────────────────────────
  165.  HEX & DECIMAL ASCII VALUES
  166.  ───────────────────────────────────────────────────────────────────────────
  167.   Style  = "H"         Hexadecimal & decimal
  168.   Row    = 1 -> x      screen row
  169.   Col    = 1 -> x      left most screen column
  170.   Cols   = 1 -> x      N° of visible columns
  171.   MustBe = 0 or x      > 0 if field is mandatory
  172.   Cased  = NOT USED
  173.   Misc   = x           max number of chars to be edited
  174.   Just   = NOT USED
  175.   Mask$  = NOT USED
  176.  
  177.   DATA IN : any string  eg: "HELLO" user sees: "48h,45h,4Ch,4Ch,4Fh"
  178.   DATA OUT: ditto                          or: "072,069,076,076,079"
  179.  
  180.   DATA IN : is a simple string "ABC" but is displayed as "41h,42h,43h"
  181.             during editing. The user also has the use of the <SPACE> key to
  182.             switch between HEX and DECimal display where "ABC" would become
  183.             "065,066,067". During editing both HEX and DECimal are accepted
  184.             and converted afterwards. Before exiting the whole mess is
  185.             cleaned up and values > 255 are rejected.
  186.   DATA OUT: "ABC" format
  187.  
  188.   The total length of the field is ( ( .Misc * 4 ) - 1 ) so .Misc
  189.     is only the individual character count and not the total space
  190.     required to show each character in HEX and/or DECimal format
  191.  
  192.  ──────────────────────────────────────────────────────────────────────────
  193.  MASKED
  194.  ──────────────────────────────────────────────────────────────────────────
  195.   Style  = "M"         Masked input
  196.   Row    = 1 -> x      screen row
  197.   Col    = 1 -> x      left most screen column
  198.   Cols   = 1 -> x      N° of visible columns (Not the mask length)
  199.   MustBe = 0 or x      > 0 if field is mandatory
  200.   Cased  = 1           1 = UCASEed input only
  201.   Misc   = NOT USED
  202.   Just   = NOT USED
  203.   Mask$  = see below   eg: "SS_A_N: NNN-NN-NNNN"
  204.  
  205.   DATA IN:  a correct data string in the prescribed format or NULL
  206.   DATA OUT: a correct data string or NULL if .MustBe = 0
  207.  
  208.   Input is strictly controlled by use of an encoded Mask$.
  209.   There are only six character types:
  210.      N = mandatory (0123456789)
  211.      n = optional  (0123456789) and <SPACE>
  212.      A = mandatory (A -> Z)
  213.      a = optional  (A -> Z) and <SPACE>
  214.      E = mandatory > <SPACE>
  215.      e = optional  anything goes!
  216.      _   preceding N,n,A,a,E, or e prints the letter
  217.      __  prints a single underline character
  218.  
  219.   Mask$, as shown above, would present "SSAN:    -  -    " to the user. As
  220.   the numbers are filled in the cursor would automatically skip the "-"'s
  221.   allowing for rapid, trouble free formatted input. The cursor can be moved
  222.   around the field but will only land on character positions requiring
  223.   input. Individual character deletion can also be done but, once again,
  224.   only on characters in the "active" positions.
  225.  
  226.   Mask$ "N-NN-NNNNNN-E" would work will for ISBNs where the last position
  227.                         "E" could be either a number or the letter "X".
  228.   Mask$ "Nn-Nn-NNnn"    could be used for dates but a poor second to the
  229.                         individual date style
  230.  
  231.  ──────────────────────────────────────────────────────────────────────────
  232.  NUMERIC
  233.  ──────────────────────────────────────────────────────────────────────────
  234.   Style  = "N"         Numbers (as values not strings)
  235.   Row    = 1 -> x      screen row
  236.   Col    = 1 -> x      left most screen column
  237.   Cols   = 1 -> x      length of Mask$
  238.   MustBe = 0 or x      > 0 if field is mandatory
  239.   Cased  = NOT USED
  240.   Misc   = NOT USED
  241.   Just   = NOT USED
  242.   Mask$  = "+#,###.#"  DO NOT USE "+####,.#" format!
  243.  
  244.   DATA IN:  incoming data is passed through VAL() to determine it's
  245.             numeric value (if any)
  246.   DATA OUT: a string suitable for conversion with VAL()
  247.  
  248.   Once again what is input is governed totally by Mask$. As shown above the
  249.   value input can be from -9,999.99 to +9,999.99. As you can see Mask$ must
  250.   be a valid format string suitable for use with USING$. If there is a
  251.   leading "+" then both positive and negative numbers will be accepted else
  252.   only positive numbers can be accepted. There seems to be a slight bug in
  253.   v3.1 that incorrectly converts "####,.##" style masks when there are two
  254.   or more commas involved in the output so use "#,###.##" just to be safe.
  255.  
  256.   Input for this field emulates that of a calculator; where the number
  257.   "grows" from right to left and only the right most character can be
  258.   erased using <DEL> or <BKSPC>. <CTRL><DEL> ZERO's the field's value.
  259.                user presses "1"    sees:      1
  260.                user presses "2"    sees:     12
  261.                user presses "3"    sees:    123
  262.                user presses "4"    sees:   1234
  263.  
  264.  ───────────────────────────────────────────────────────────────────────────
  265.  PATH
  266.  ───────────────────────────────────────────────────────────────────────────
  267.   Style  = "P"         DOS Path's, file names, etc.
  268.   Row    = 1 -> x      screen row
  269.   Col    = 1 -> x      left most screen column
  270.   Cols   = 1 -> x      N° of visible columns
  271.   MustBe = 0 or x      > 0 if field is mandatory
  272.   Cased  = 2           2 = LCASEed (UCASE is assumed)
  273.   Misc   = x           maximum field length => Cols
  274.   Just   = NOT USED
  275.   Mask$  = ":\.?*"     any or all of these chars but NO OTHERS please
  276.                        any character can be made available however
  277.  
  278.   DATA IN : any legal DOS string value from NULL to .Misc in length
  279.  
  280.   This field is, in fact, only a sub-set of the Alpha field. It adds to
  281.   the Mask$ you send all the legal DOS characters except the 5 listed
  282.   above. As you can see these 5 control the field's ability to input
  283.   drive and/or path information and/or wild cards. It also defaults to
  284.   upper case conversion unless you send an explicit value of 2 for .Cased
  285.  
  286.   Some testing is done on the input string in an attempt to forestall user
  287.   mistakes but it's not perfect as no one can tell just what a user will do
  288.   when given a chance ;)
  289.  
  290.  ──────────────────────────────────────────────────────────────────────────
  291.  QUERY
  292.  ──────────────────────────────────────────────────────────────────────────
  293.   Style  = "Q"         Query or Questions
  294.   Row    = 1 -> x      screen row
  295.   Col    = 1 -> x      left most screen column
  296.   Cols   = 1 -> x      N° of visible columns
  297.   MustBe = 0 or x      > 0 if field is mandatory
  298.   Cased  = NOT USED    UCASE only
  299.   Misc   = x           maximum field length => Cols
  300.   Just   = NOT USED
  301.   Mask$  = see below   "MFN?|Male|Female|Not Disclosed|(Male,Female,None)"
  302.  
  303.   DATA IN : a single character
  304.             if NULL then the left most character in Mask$ is assumed
  305.   DATA OUT: one of the characters in the 1st field of Mask$ (except "?")
  306.  
  307.   This field acts as a mini-menu. Mask$ is cut into several pieces by the
  308.   pipe "|" character. The first (left most) field are the legal selections
  309.   with their long versions following in order. As the long versions are what
  310.   the user sees .Cols must always represent the longest of the set.
  311.  
  312.   If the question mark "?" is used it must be the last selection and will
  313.   cause the final field to be displayed in the event the user presses an
  314.   illegal key. It can not be returned as an answer.
  315.  
  316.   Using Mask$ as we have it above:
  317.   The user may press "M", "F", or "N" to get an acceptable answer and
  318.   immediate exit from the field. Assuming the "M" is pressed the string
  319.   "Male" will be printed on the screen. If, however, the "?" were pressed
  320.   then "(Male, Female or None)" would be displayed for 2 seconds and would
  321.   either exit upon a valid key or revert back to the original value if the
  322.   time elapsed first.
  323.  
  324.   NOTE: an approximation of this process can be duplicated by using the
  325.         Alpha field with .Cols  = 1
  326.                          .Cased = 1
  327.                           Mask$ = "MFN"
  328.  
  329.   HINT: if you want your answers printed with color commands (like the
  330.         first letter blue and the rest grey) use a color attribute value
  331.         of ZERO for the normal attribute then embed the color command
  332.         in the answer pieces
  333.  
  334.  ───────────────────────────────────────────────────────────────────────────
  335.  TIMES
  336.  ───────────────────────────────────────────────────────────────────────────
  337.   Style  = "T"         Times
  338.   Row    = 1 -> x      screen row
  339.   Col    = 1 -> x      left most screen column
  340.   Cols   = 6 or 9      6 is default
  341.   MustBe = 0 or x      > 0 if field is mandatory
  342.   Cased  = NOT USED
  343.   Misc   = NOT USED
  344.   Just   = NOT USED
  345.   Mask$  = NOT USED
  346.  
  347.  
  348.  DATA  IN: a 6 or 9 char time string  eg: "HH:MM " or "HH:MM:SSx"
  349.  DATA OUT: same format as data in          SEE: SetTimeFormat
  350.  
  351.  if .MustBe > 0 and incoming D$ is NULL then the system's time will
  352.  be automatically loaded
  353.  input style is dependent upon the values in SetTimeFormat
  354.  
  355.  NOTE: times are ALWAYS edited as 24 hour clocks avoiding the "a" and "p"
  356.  
  357.  ───────────────────────────────────────────────────────────────────────────
  358.  ────                                                                   ────
  359.  ───────────────────────────────────────────────────────────────────────────
  360.  fTinput$  ( {D$}, Control$, ExitKeys$, Nattr?, Hattr? )
  361.  fTinputM$ ( {D$}, Control$, ExitKeys$, Nattr?, Hattr?, HotSpot% )
  362.    D$        is both the incoming and exiting data
  363.              if NULL then incoming data has failed some internal test
  364.                      or has a value of ZERO for "N"umbers
  365.    Control$  is a construct of ( TinputTYPE + Mask$ )
  366.              just a quick word here just in case it isn't quite clear what
  367.              we are looking for:
  368.              TinputTYPE is used to convert the first 8 characters of
  369.              Control$ into the separate members while Mask$ is actually
  370.              cut out of the middle. LSET tINP  = LEFT$( Control$, 8 )
  371.                                          Mask$ =  MID$( Control$, 9 )
  372.              The reason this is done is to simplify storage of control
  373.              strings in data files. You can, of course, use the TYPE in
  374.              your code too.
  375.    ExitKeys$ has 2 default keys loaded by the function:
  376.              CHR$(13) <ENTER>  = acceptance of the data
  377.              CHR$(27) <ESC>    = disregard changes/restore original value
  378.              You may add any other key(s) you wish.
  379.              F-1 and F-10 would be ExitKeys$ = CHR$(0,59,0,68)
  380.    Nattr?    is the color attribute to use upon exiting the field
  381.    Hattr?    is the color attribute to use while the field is being edited
  382.    HotSpot%  the item number for the field being edited
  383.  
  384.    fTinput$  RETURNS CHR$(?)   exiting key-press
  385.    fTinputM$ RETURNS CHR$(?)   exiting key-press
  386.                      NULL      mouse clicked in another item of current event
  387.                      CHR$(255) mouse clicked in another event
  388.  ───────────────────────────────────────────────────────────────────────────
  389.  The following keys are default unless also found in ExitKeys$
  390.  
  391.  <BkSpc>       delete character to the left of the cursor
  392.  <HOME>        cursor to #1 character position
  393.  <LEFT>        move cursor 1 position left
  394.  <RIGHT>       move cursor 1 position right
  395.  <END>         cursor to end of data or last character position
  396.  <INS>         toggle insert ON/OFF   SEE: fINSERTmsg%
  397.  <DEL>         delete character under the cursor
  398.  <CTRL><LEFT>  next word left
  399.  <CTRL><RIGHT> next word right
  400.  <CTRL><DEL>   erase all data in the field
  401.  
  402.  <ENTER>       exit field, accept new data
  403.  <ESC>         exit field, keep original data
  404.  
  405.  NOTE: some of these keys have no effect on some of the field styles.
  406.        ( Logic dictates here. ie: CTRL/LEFT and Numerics isn't a match )
  407.        If a key cannot be used by any field style it is simply ignored.
  408.  
  409.  Even though each field can handle incoming NULL values for the data  I've
  410.  found it best to supply whatever defaults your program may require.  Even
  411.  on the odd chance that the style's idea of a default value is the same as
  412.  the program's there is no guarantee  that the user will pass through that
  413.  particular field. This would leave your data "out of shape" and may cause
  414.  problems in other portions of the program. It is much safer to <KNOW> the
  415.  data is in the proper format throughout the program than to be constantly
  416.  checking it. ( Saves on the Raid bill, too... :)
  417.  
  418. ════════════════════════════════════════════════════════════════════════════
  419. ═════                   putting it all together                        ═════
  420. ════════════════════════════════════════════════════════════════════════════
  421.  
  422.  So far I've only been talking about single fields and that, no matter how
  423.  good it is, is only the tip of the iceberg. Greater things are afoot here
  424.  and can now be addressed.
  425.  
  426.  More times than not there is more that one field of data that needs to
  427.  be input. One medical program I built years ago had over 2,500 fields for
  428.  each record spread over 40 different screens, and without a consolidated
  429.  screen input routine I would still be writing code for them all. Enter
  430.  the arrays! Now no matter how many fields your screens may have, you can
  431.  simply pack the data and control strings for each field into arrays and
  432.  put the whole process into a single loop. By loading ExitKeys$ with <UP>,
  433.  <DOWN>, <F-10>, etc. you can easily control movement within the array.
  434.  Then (and you thought I forgot) by using the .Just member of the TYPE
  435.  your loop can be made to perform field specific checking, rejection and
  436.  message warnings, or any one of a dozen other tasks quite simply!
  437.  SEE: fJustify$
  438.  
  439.  As it is a very real possibility that not all programs will require all
  440.  the field styles, each style is split into a separate .INC file.
  441.  TINPUT.UNT has 9 integer constants at the beginning of the file that will
  442.  either include or exclude each of the TINPUT_?.INC files. This allows you
  443.  to keep your programs down to their proper size without a batch of useless
  444.  code laying around.
  445.  
  446.  The following files are required:
  447.    TINPUT  .TYP     ' the type declaration
  448.    TINPUT  .UNT     ' fTinput$ and all the supporting routines
  449.    TINPUTM .UNT     ' fTinputM$ and it's supporting routines (Mouse Aware)
  450.    TINPUT_A.INC     ' Alpha input
  451.    TINPUT_B.INC     ' Blocks
  452.    TINPUT_D.INC     ' Dates         ( requires TINPUT_M.INC )
  453.    TINPUT_H.INC     ' Hex & Decimal ( requires TINPUT_A.INC )
  454.    TINPUT_M.INC     ' Masked
  455.    TINPUT_N.INC     ' Numbers
  456.    TINPUT_P.INC     ' Path          ( requires TINPUT_A.INC )
  457.    TINPUT_Q.INC     ' Query
  458.    TINPUT_T.INC     ' Times         ( requires TINPUT_M.INC )
  459.  
  460.  fTinput2$ ( SEG D$(), SEG F$(), SEG T?(), SEG H$(), SEG Fld% )
  461.    D$() all the incoming/outgoing data for the fields
  462.    F$() all the control strings
  463.    T?() if UBOUND(T?(1)) > 0 then the field numbers to be tabbed to
  464.         the field numbers must be in ascending order
  465.    H$() if UBOUND(H$(1)) > 0 then the help strings are printed by
  466.         calling fHelpLine$
  467.    Fld% the field to start processing at
  468.  
  469.    This routine is ready to be input directly into your programs, but you
  470.    will probably want to modify it to fit your exact needs. The "tab fields"
  471.    is a handy gizmo if your program uses some monster input screens
  472.    but really does very little on the small stuff and would just be a
  473.    nuisance. Rip it out! Ditto with the help line. I like it (obviously)
  474.    and use it constantly but.....
  475.    There is no reason that you couldn't compile it and stuff it in the
  476.    .PBL but I don't think I've every written 2 programs that were enough
  477.    alike to do that and that is why it's an .INC file.
  478.  
  479.    The last little part is the use of fJustify$. The individual field
  480.    routines are pretty smart to start with and you may find that fJustify$
  481.    just gets in the way. No problemo... <CTRL>Y is at your beck n' call!
  482.  
  483.  In TINPUT.DMO I've hung the whole thing together so you could see it in
  484.  action, and play with it.
  485.  
  486.  fJustify$ is also, finally, put to some practical use in this file. It
  487.  really doesn't have a lot of use in the demo but I'm sure you will get
  488.  the general idea. It is not inconceivable that you could construct yet
  489.  another function ( fPreJust$ ) to load default values! Two old saws come
  490.  to mind:
  491.                   "Never write the same code twice."
  492.                   "There are exceptions to every rule."
  493.  
  494.   Last minute entry:
  495.     fQueryPrint$ ( Row?, Col?, Cols?, Mask$, Answer$ )
  496.     This one was added as a good afterthought to all of this. If you
  497.     remember the Query field you know that the incoming/outgoing data is
  498.     a single letter that is found in the first piece of Mask$ and that the
  499.     first answer is default if Answer$ is NULL.
  500.                        Mask$ = "YNM|Yes|No|Maybe"
  501.     fQueryPrint$ will return the correct piece of Mask$ and if Row? > ZERO
  502.     will use TprintCLEAR with an attribute of ZERO to print the string.
  503.     While writing a small, small program for a local business I just got
  504.     tired of doing the 2 or 3 lines of code necessary to make all this
  505.     happen, so.......
  506.  
  507.  See you in TINPUT.DMO!